<template>
  <div class="slider-captcha">
    <div class="slider-captcha-container">
      <!-- 验证码图片区域 -->
      <div class="captcha-image-container">
        <div class="captcha-bg" :style="{ backgroundImage: `url(${bgImage})` }">
          <!-- 缺口 -->
          <div class="gap" :style="{ left: `${gapPosition}px` }"></div>
        </div>
        <!-- 滑块块 -->
        <div class="slider-piece" 
             :style="{ 
               backgroundImage: `url(${bgImage})`,
               backgroundPosition: `-${gapPosition}px 0px`,
               left: `${sliderPosition}px`
             }">
        </div>
      </div>
      
      <!-- 滑块轨道 -->
      <div class="slider-track">
        <div class="slider-button" 
             :style="{ left: `${sliderPosition}px` }"
             @mousedown="startDrag"
             @touchstart="startDrag">
          <svg-icon icon-class="right" class="slider-icon" />
        </div>
        <div class="slider-text">{{ sliderText }}</div>
      </div>
      
      <!-- 刷新按钮 -->
      <div class="refresh-btn" @click="refreshCaptcha">
        <svg-icon icon-class="refresh" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

interface Props {
  width?: number
  height?: number
}

const props = withDefaults(defineProps<Props>(), {
  width: 300,
  height: 200
})

const emit = defineEmits<{
  success: [data: { x: number, y: number, token: string }]
  fail: []
}>()

// 状态变量
const bgImage = ref('')
const gapPosition = ref(0)
const sliderPosition = ref(0)
const sliderText = ref('向右滑动完成验证')
const isDragging = ref(false)
const startX = ref(0)
const startSliderX = ref(0)
const captchaToken = ref('')

// 生成随机缺口位置
const generateGapPosition = () => {
  const minGap = 50
  const maxGap = props.width - 50
  gapPosition.value = Math.floor(Math.random() * (maxGap - minGap)) + minGap
  captchaToken.value = Math.random().toString(36).substring(2, 15)
  // 重置滑块位置
  sliderPosition.value = 0
}

// 生成背景图片
const generateBgImage = () => {
  const canvas = document.createElement('canvas')
  canvas.width = props.width
  canvas.height = props.height
  const ctx = canvas.getContext('2d')
  
  if (ctx) {
    // 绘制背景
    const gradient = ctx.createLinearGradient(0, 0, props.width, props.height)
    gradient.addColorStop(0, '#e3f2fd')
    gradient.addColorStop(1, '#bbdefb')
    ctx.fillStyle = gradient
    ctx.fillRect(0, 0, props.width, props.height)
    
    // 绘制随机圆点
    for (let i = 0; i < 50; i++) {
      ctx.beginPath()
      ctx.arc(
        Math.random() * props.width,
        Math.random() * props.height,
        Math.random() * 10 + 5,
        0,
        2 * Math.PI
      )
      ctx.fillStyle = `rgba(33, 150, 243, ${Math.random() * 0.5 + 0.3})`
      ctx.fill()
    }
    
    bgImage.value = canvas.toDataURL()
  }
}

// 开始拖拽
const startDrag = (e: MouseEvent | TouchEvent) => {
  e.preventDefault()
  isDragging.value = true
  startX.value = 'touches' in e ? e.touches[0].clientX : e.clientX
  startSliderX.value = sliderPosition.value
  
  document.addEventListener('mousemove', onDrag)
  document.addEventListener('mouseup', stopDrag)
  document.addEventListener('touchmove', onDrag)
  document.addEventListener('touchend', stopDrag)
}

// 拖拽中
const onDrag = (e: MouseEvent | TouchEvent) => {
  if (!isDragging.value) return
  
  const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX
  const deltaX = clientX - startX.value
  const newPosition = startSliderX.value + deltaX
  
  // 限制滑块范围
  sliderPosition.value = Math.max(0, Math.min(newPosition, props.width - 40))
}

// 停止拖拽
const stopDrag = () => {
  if (!isDragging.value) return
  
  isDragging.value = false
  
  // 检查是否验证成功
  const tolerance = 5
  const isSuccess = Math.abs(sliderPosition.value - gapPosition.value) <= tolerance
  
  if (isSuccess) {
    sliderText.value = '验证成功'
    emit('success', {
      x: gapPosition.value,
      y: props.height / 2,
      token: captchaToken.value
    })
  } else {
    sliderText.value = '验证失败，请重试'
    setTimeout(() => {
      resetSlider()
    }, 1000)
    emit('fail')
  }
  
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.removeEventListener('touchmove', onDrag)
  document.removeEventListener('touchend', stopDrag)
}

// 重置滑块
const resetSlider = () => {
  sliderPosition.value = 0
  sliderText.value = '向右滑动完成验证'
}

// 刷新验证码
const refreshCaptcha = () => {
  generateGapPosition()
  generateBgImage()
  resetSlider()
}

// 暴露方法
defineExpose({
  refreshCaptcha
})

// 初始化
onMounted(() => {
  generateGapPosition()
  generateBgImage()
})

// 清理
onUnmounted(() => {
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.removeEventListener('touchmove', onDrag)
  document.removeEventListener('touchend', stopDrag)
})
</script>

<style scoped lang="scss">
.slider-captcha {
  width: 100%;
  
  .slider-captcha-container {
    position: relative;
    width: 100%;
    background: #f8fafc;
    border-radius: 8px;
    padding: 20px;
    border: 1px solid #e2e8f0;
  }
  
  .captcha-image-container {
    position: relative;
    width: 100%;
    height: 200px;
    margin-bottom: 20px;
    border-radius: 6px;
    overflow: hidden;
  }
  
  .captcha-bg {
    width: 100%;
    height: 100%;
    background-size: cover;
    background-position: center;
    position: relative;
    
    .gap {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      width: 40px;
      height: 40px;
      background: rgba(255, 255, 255, 0.8);
      border: 2px solid #3b82f6;
      border-radius: 4px;
    }
  }
  
  .slider-piece {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    background-size: cover;
    border: 2px solid #3b82f6;
    border-radius: 4px;
    cursor: move;
    z-index: 10;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  }
  
  .slider-track {
    position: relative;
    width: 100%;
    height: 40px;
    background: #e2e8f0;
    border-radius: 20px;
    display: flex;
    align-items: center;
    
    .slider-button {
      position: absolute;
      width: 40px;
      height: 40px;
      background: #3b82f6;
      border-radius: 50%;
      cursor: grab;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
      transition: all 0.2s ease;
      
      &:hover {
        background: #2563eb;
      }
      
      &:active {
        cursor: grabbing;
        transform: scale(0.95);
      }
      
      .slider-icon {
        font-size: 16px;
      }
    }
    
    .slider-text {
      flex: 1;
      text-align: center;
      color: #64748b;
      font-size: 14px;
      user-select: none;
    }
  }
  
  .refresh-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 32px;
    height: 32px;
    background: #f1f5f9;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #64748b;
    transition: all 0.2s ease;
    
    &:hover {
      background: #e2e8f0;
      color: #3b82f6;
    }
  }
}
</style>
